#include "RingQueue.hpp"
#include "Task.hpp"
#include <ctime>   //时间戳需要
#include <cstdlib> //srand需要

#include <sys/types.h> //gerpid需要这两个头文件
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

std::string ThreadName() // 哪一个线程调用，就打印该线程的名字
{
    char name[128];
    snprintf(name, sizeof name, "thread[0x%x]", pthread_self());
    return name;
}

void *producerRoutine(void *args)
{
    RingQueue<CalTask> *ringqueue = static_cast<RingQueue<CalTask> *>(args);
    while (true)
    {
        // int data = rand() % 10 + 1;
        // ringqueue->Push(data);

        // pthread_mutex_lock(&mutex);
        // cout << " 生产完成，生产数据 : " << data << endl;
        // pthread_mutex_unlock(&mutex);

        // sleep(1); // 生产慢一点，我慢了，你必须也慢下来 —— 典型的同步

        // 构建or获取任务
        int x = rand() % 10;
        int y = rand() % 5;
        char op = rand() % oper.size();
        CalTask t(x, y, oper[op], my_math);
        // 生产任务
        ringqueue->Push(t);
        // printf("生产生产了一个任务 : %s\n", t.TaskToString().c_str());
        pthread_mutex_lock(&mutex);
        cout << ThreadName() << " 生产生产了一个任务 : " << t.TaskToString() << endl;
        pthread_mutex_unlock(&mutex);
    }
}

void *ConsumerRoutine(void *args)
{
    RingQueue<CalTask> *ringqueue = static_cast<RingQueue<CalTask> *>(args);
    while (true)
    {
        // int data;
        // ringqueue->Pop(&data);

        // pthread_mutex_lock(&mutex);
        // cout << " 消费完成，消费数据 : " << data << endl;
        // pthread_mutex_unlock(&mutex);

        CalTask t;
        ringqueue->Pop(&t);
        std::string result = t();
        // printf("消费消费了一个任务 : %s\n", result.c_str());
        pthread_mutex_lock(&mutex);
        cout << ThreadName() << " 消费消费了一个任务 : " << result << endl;
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    srand((unsigned int)time(nullptr) ^ getpid() ^ pthread_self());
    RingQueue<CalTask> *rq = new RingQueue<CalTask>();
    pthread_t p[4], c[8];
    for (int i = 0; i < 4; ++i)
        pthread_create(p + i, nullptr, producerRoutine, rq);
    for (int i = 0; i < 8; ++i)
        pthread_create(c + i, nullptr, ConsumerRoutine, rq);

    for (int i = 0; i < 4; ++i)
        pthread_join(p[i], nullptr);
    for (int i = 0; i < 8; ++i)
        pthread_join(c[i], nullptr);
    delete rq;
    return 0;
}